#    Copyright 2014 Gregory Roby
#    This file is part of COOPGIS.
#    COOPGIS is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#    COOPGIS is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#    You should have received a copy of the GNU General Public License
#    along with COOPGIS.  If not, see <http://www.gnu.org/licenses/>.


#Import Shape File Examples



#************************BEGIN Add Include Files to Path************************
import sys
NeededPaths=['/opt/coopgis/djangoproject/include', '/opt/coopgis/djangoproject']
for path in NeededPaths:
    if(not path in sys.path):
        sys.path.append(path)
#************************END   Add Include Files to Path************************
import application, cis, command, compatibleunit, oms, staker, symbology, unsorted
import COOPGIS_Ajax, COOPGIS_GPS, COOPGIS_Misc, COOPGIS_ReportLab, COOPGIS_String, COOPGIS_Update
import os, csv, shutil, datetime, time, reportlab, djangoproject.settings
from django.contrib.gis.db import models
from django.contrib.gis.geos import *
from django.http import HttpResponse
from django.contrib.gis import admin
import _mysql as mysql
import django.contrib.gis.measure
from django.contrib.gis.measure import Distance


def SplitWirePhases(span):
    Assemblies=compatibleunit.Assembly.objects.filter(Span=span).filter(CompatibleUnit__ConductorIndicator=True)
    for i in Assemblies:
        NumberOfPhases=GetNumberOfPhases(i)
        while(NumberOfPhases > i.CompatibleUnit.ConductorNumberOfWires):
            if(i.CompatibleUnit.ConductorNumberOfWires < 1):
                raise('Compatible Unit:  ' + str(i.CompatibleUnit.Name) + ' has fewer then 1 ConductorNumberOfWires.')
            New=compatibleunit.Assembly()
            New.CompatibleUnit=i.CompatibleUnit
            New.CircuitNumber=i.CircuitNumber
            New.IdleIndicator=i.IdleIndicator
            New.PrimaryIndicator=i.PrimaryIndicator
            New.SecondaryIndicator=i.SecondaryIndicator
            New.ServiceIndicator=i.ServiceIndicator
            New.Rotation=i.Rotation
            New.Quantity=1
            New.AssemblyOwner=i.AssemblyOwner
            New.Span=i.Span
            New.ResidesOnServerIndicator=i.ResidesOnServerIndicator
            if(i.PhaseNeutralIndicator):  #Only one of these will be executed, so only one phase will be assigned to the new wire each time through the loop.
                New.PhaseNeutralIndicator=True
                i.PhaseNeutralIndicator=False
            elif(i.PhaseAIndicator):
                New.PhaseAIndicator=True
                i.PhaseAIndicator=False
            elif(i.PhaseBIndicator):
                New.PhaseBIndicator=True
                i.PhaseBIndicator=False
            elif(i.PhaseCIndicator):
                New.PhaseCIndicator=True
                i.PhaseCIndicator=False
            else:
                raise('Wire had no Phases')
            New.save()
            i.save()
            NumberOfPhases=GetNumberOfPhases(i)

def CombineWirePhases(span):
    Assemblies=compatibleunit.Assembly.objects.filter(Span=span).filter(CompatibleUnit__ConductorIndicator=True)
    #Initial Implementation will seek to just work most of the time (w/ no data corruption obviously) and may
    #Need to be run multiple times on a span, later on can be expanded if desired
    Target=None
    for i in Assemblies:
        if(GetNumberOfPhases(i) < i.CompatibleUnit.ConductorNumberOfWires):
            Target=i
            break
    if(not Target): #End Now if no Wires that can be combined...
        return
    Assemblies=compatibleunit.Assembly.objects.filter(Span=span, CompatibleUnit=Target.CompatibleUnit).exclude(id__exact=Target.id)
    for i in Assemblies:
        if(GetNumberOfPhases(i) < (Target.CompatibleUnit.ConductorNumberOfWires - GetNumberOfPhases(Target))):
            if(i.PhaseAIndicator and not Target.PhaseAIndicator):
                i.PhaseAIndicator=False
                Target.PhaseAIndicator=True
            elif(i.PhaseBIndicator and not Target.PhaseBIndicator):
                i.PhaseBIndicator=False
                Target.PhaseBIndicator=True
            elif(i.PhaseCIndicator and not Target.PhaseCIndicator):
                i.PhaseCIndicator=False
                Target.PhaseCIndicator=True
            elif(i.PhaseNeutralIndicator and not Target.PhaseNeutralIndicator):
                i.PhaseNeutralIndicator=False
                Target.PhaseNeutralIndicator=True
            Target.save()
            i.save()
            if(not i.PhaseAIndicator and not i.PhaseBIndicator and not i.PhaseCIndicator and not i.PhaseNeutralIndicator):
                i.delete()
    

def CleanupSpans():
    Spans=Span.objects.all()
    for span in Spans:
        SplitWirePhases(span) 
    for span in Spans:
        CombineWirePhases(span)

#********************************************************************************
#***All Network Features will be Geographically placed into a Station or Span****
#********************************************************************************
class Station(models.Model):
    """Station holds the location information for all electrical equipment"""
    Description=models.TextField()
    TransformerUsageAnalysisComment=models.TextField(db_column='transformerusageanalysiscomment', null=True, blank=True)
    Point=models.PointField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    objects=models.GeoManager()
    ResidesOnServerIndicator=models.NullBooleanField(blank=True, null=True)
    CreateCommand=models.ForeignKey('Command', blank=True, null=True, on_delete=models.SET_NULL)
    SymbologyCompatibleUnits=models.TextField(blank=True, null=True, db_column='symbologycompatibleunits')
    SymbologyInstallIndicator=models.NullBooleanField(blank=True, null=True, db_column='symbologyinstallindicator')
    SymbologyExistingIndicator=models.NullBooleanField(blank=True, null=True, db_column='symbologyexistingindicator')
    SymbologyRemoveIndicator=models.NullBooleanField(blank=True, null=True, db_column='symbologyremoveindicator')
    SymbologyGroundRodTestYear=models.IntegerField(db_column='symbologygroundrodtestyear', null=True, blank=True)
    #CompatibleUnitOneName, CompatibleUnitOneNumber, CompatibleUnitTwoName, and CompatibleUnitTwoNumber allow for quick maps of where various compatibleunits are installed at
    CompatibleUnitOneName=models.TextField(db_column='compatibleunitonename', null=True, blank=True) 
    CompatibleUnitOneNumber=models.IntegerField(db_column='compatibleunitonenumber', null=True, blank=True)
    CompatibleUnitTwoName=models.TextField(db_column='compatibleunittwoname', null=True, blank=True) 
    CompatibleUnitTwoNumber=models.IntegerField(db_column='compatibleunittwonumber', null=True, blank=True)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisstation'
        app_label='djangoproject'
    def CombineLikeStationAssemblies(self, AssemblyList):
        CombinedAssemblyList=[]
        CombinationsAdded=[]
        for i in range(0, len(AssemblyList)):
            CountOfCurrentAssembly=0
            for j in range(0, len(AssemblyList)):
                if(AssemblyList[i].CompatibleUnit.Name == AssemblyList[j].CompatibleUnit.Name):
                    CountOfCurrentAssembly = CountOfCurrentAssembly + 1
            if(not ('Assembly:  ' + str(AssemblyList[i]) in CombinationsAdded)):
                CurrentAssemblyName=AssemblyList[i].CompatibleUnit.Name
                CurrentAssemblies=compatibleunit.Assembly.objects.filter(Station=self).filter(CompatibleUnit__Name=CurrentAssemblyName).exclude(InstallStatus__Name='Install')
                PhaseCodeString=' [' + CurrentAssemblies[0].GetSumOfPhaseCodes(CurrentAssemblies) + ']'
                if(PhaseCodeString == ' []'):
                    PhaseCodeString = ''
                if(CountOfCurrentAssembly == 1):
                    CombinedAssemblyList.append(str(AssemblyList[i]) + PhaseCodeString)
                else:
                    CombinedAssemblyList.append(str(CountOfCurrentAssembly) + '-' + str(AssemblyList[i]) + PhaseCodeString)
                CombinationsAdded.append('Assembly:  ' + str(AssemblyList[i]))
        return CombinedAssemblyList
    def UpdateSymbology(self):
        Assemblies=compatibleunit.Assembly.objects.all().filter(Station=self).exclude(InstallStatus__Name='Install')
        TagNumbers=[]
        CompatibleUnitList=self.CombineLikeStationAssemblies(Assemblies)
        for assembly in Assemblies:
            if(assembly.TagNumber):
                TagNumbers.append('#' + str(assembly.TagNumber))
        CompatibleUnitList.append(', '.join(TagNumbers))
        self.SymbologyCompatibleUnits=str(self.id) + ": l " + ','.join(CompatibleUnitList)
        GroundRodTests=compatibleunit.GroundRodTest.objects.filter(StationIdentifier=self.id).order_by('-CreateDateTime')
        if(GroundRodTests.count()):
            self.SymbologyGroundRodTestYear=GroundRodTests[0].CreateDateTime.year
        else:
            self.SymbologyGroundRodTestYear=None
        if(compatibleunit.Assembly.objects.filter(Station=self).filter(InstallStatus__Name='Install')):
            self.SymbologyInstallIndicator=True
        else:
            self.SymbologyInstallIndicator=False
        if(compatibleunit.Assembly.objects.filter(Station=self).filter(InstallStatus__Name='Existing')):
            self.SymbologyExistingIndicator=True
        else:
            self.SymbologyExistingIndicator=False
        if(compatibleunit.Assembly.objects.filter(Station=self).filter(InstallStatus__Name='Remove')):
            self.SymbologyRemoveIndicator=True
        else:
            self.SymbologyRemoveIndicator=False
        self.save()
    @staticmethod
    def GetOrCreate(Point, Description='', OnlyFromSelf=False, CreateCommand=None):
        if(not OnlyFromSelf):  #Check to make sure called by GetOrCreateClosestStation
	    raise('Cannot GetOrCreate a Station Directly, use GetOrCreateClosestStation')
        ExistingStation=False
        try:
            New=Station.objects.get(Point=Point)
            ExistingStation=True
            return New
        except:
            pass
        New=Station()
        New.Point=Point
        New.Description=Description
        New.ResidesOnServerIndicator=djangoproject.settings.COOPGISServerIndicator
        New.CreateCommand=CreateCommand
        New.save()
        New.RebuildSymbology()
        return New
    @staticmethod
    def GetOrCreateClosestStation(InputPoint, StartDistance=1, MaximumDistance=1.5, Step=.25, Description='', CreateCommand=None):
        """GetOrCreateClosestStation returns the closest station to the InputPoint or creates a new one if none are found"""
	if(StartDistance < 1):
	    StartDistance = 1   #If there is an existing station within 1 foot, then use it, all stations are at least be 1 foot apart 
        CurrentDistance=StartDistance
        while(CurrentDistance<MaximumDistance):
            Results=Station.objects.filter(Point__distance_lte=(InputPoint, CurrentDistance * djangoproject.settings.COOPGISDistanceMultiplier))
            if(Results):
                return Results[0]
            CurrentDistance=CurrentDistance+Step
        New=Station.GetOrCreate(InputPoint, OnlyFromSelf=True, Description=Description, CreateCommand=CreateCommand)
        New.RebuildSymbology()   
        return New 
    def __unicode__(self):
        if(self.Description):
            return str(self.id) + ':  ' + self.Description
        else:
            return str(self.id)
    def StringDetailed(self):
        StringList=[]
	StringList.append('#' + str(self.id))
	NearbyRoads=Road.objects.filter(Line__distance_lte=(self.Point, 9000 * djangoproject.settings.COOPGISDistanceMultiplier))
	ClosestRoad=''
	ClosestDistance=9000 * djangoproject.settings.COOPGISDistanceMultiplier
	for i in NearbyRoads:
	   if(self.Point.distance(i.Line) < ClosestDistance):
	       ClosestDistance=self.Point.distance(i.Line)
               ClosestRoad=i.Name
        try:
            StringList.append(str(int(ClosestDistance)) + " feet away:  " + ClosestRoad)
        except:
            pass

        Assemblies = djangoproject.models.compatibleunit.Assembly.objects.filter(Station=self)
        Poles = Assemblies.filter(CompatibleUnit__PoleIndicator=True)
        PoleList = [i.StringDetailed() for i in Poles]
        StringList += PoleList
        Transformers = Assemblies.filter(CompatibleUnit__PoleIndicator=False,
                                         CompatibleUnit__TransformerIndicator=True)
        TransformerList = [i.StringDetailed() for i in Transformers]
        StringList += TransformerList
        StakerUnits = Assemblies.filter(CompatibleUnit__PoleIndicator=False,
                                        CompatibleUnit__TransformerIndicator=False,
                                        CompatibleUnit__StakerUnitIndicator=True)
        StakerUnitList = [i.StringDetailed() for i in StakerUnits]
        StringList += StakerUnitList
        Grounds = Assemblies.filter(CompatibleUnit__PoleIndicator=False,
                                    CompatibleUnit__TransformerIndicator=False,
                                    CompatibleUnit__StakerUnitIndicator=False,
                                    CompatibleUnit__GroundIndicator=True)
        GroundList = [i.StringDetailed() for i in Grounds]
        StringList += GroundList
        StakerGuyGuys = Assemblies.filter(CompatibleUnit__PoleIndicator=False,
                                          CompatibleUnit__TransformerIndicator=False,
                                          CompatibleUnit__StakerUnitIndicator=False,
                                          CompatibleUnit__GroundIndicator=False,
                                          CompatibleUnit__StakerGuyGuyIndicator=True)
        StakerGuyGuyList = [i.StringDetailed() for i in StakerGuyGuys]
        StringList += StakerGuyGuyList
        StakerGuyMarkers = Assemblies.filter(CompatibleUnit__PoleIndicator=False,
                                             CompatibleUnit__TransformerIndicator=False,
                                             CompatibleUnit__StakerUnitIndicator=False,
                                             CompatibleUnit__GroundIndicator=False,
                                             CompatibleUnit__StakerGuyGuyIndicator=False,
                                             CompatibleUnit__StakerGuyMarkerIndicator=True)
        StakerGuyMarkerList = [i.StringDetailed() for i in StakerGuyMarkers]
        StringList += StakerGuyMarkerList
        StakerGuyAnchors = Assemblies.filter(CompatibleUnit__PoleIndicator=False,
                                          CompatibleUnit__TransformerIndicator=False,
                                          CompatibleUnit__StakerUnitIndicator=False,
                                          CompatibleUnit__GroundIndicator=False,
                                          CompatibleUnit__StakerGuyGuyIndicator=False,
                                          CompatibleUnit__StakerGuyMarkerIndicator=False,
                                          CompatibleUnit__StakerGuyAnchorIndicator=True)
        StakerGuyAnchorList = [i.StringDetailed() for i in StakerGuyAnchors]
        StringList += StakerGuyAnchorList
        OtherCompatibleUnits = Assemblies.filter(CompatibleUnit__PoleIndicator=False,
                                          CompatibleUnit__TransformerIndicator=False,
                                          CompatibleUnit__StakerUnitIndicator=False,
                                          CompatibleUnit__GroundIndicator=False,
                                          CompatibleUnit__StakerGuyGuyIndicator=False,
                                          CompatibleUnit__StakerGuyMarkerIndicator=False,
                                          CompatibleUnit__StakerGuyAnchorIndicator=False)
        OtherCompatibleUnitList = [i.StringDetailed() for i in OtherCompatibleUnits]
        StringList += OtherCompatibleUnitList

        
        
        QuantityStringList=[]
        for i in StringList:
            if(StringList.count(i) > 1):
                NewString='(' + str(StringList.count(i)) + ') ' + i
                if(not NewString in QuantityStringList):
                    QuantityStringList.append(NewString)
            else:
                QuantityStringList.append(i)
        Treatments=djangoproject.models.compatibleunit.PoleTreatment.objects.filter(Pole__Station=self)
        for i in Treatments:
            QuantityStringList.append('Treatment:  ' + i.Company.Name)
        JointUses=djangoproject.models.compatibleunit.PoleJointUse.objects.filter(Station=self)
        for i in JointUses:
            QuantityStringList.append('Joint Use:  ' + i.Company.Name)

        return ', '.join(QuantityStringList)
    def RebuildSymbology(self, EntireMap=False, RelatedSpanStationOnly=None):
        if(EntireMap):
            station=None
        else:
            station=self
        if(RelatedSpanStationOnly):  #Rebuild Symbology for "splitting assemblies" on the farside of a span
            symbologyCutOut=symbology.SymbologyCutOut()
            symbologyCutOut.BuildSymbology(station=self)            
            symbologyNonProtectingAssembly=symbology.SymbologyNonProtectingAssembly()
            symbologyNonProtectingAssembly.BuildSymbology(station=self)      
            symbologyOpenPoint=symbology.SymbologyOpenPoint()
            symbologyOpenPoint.BuildSymbology(station=self)  
            symbologyRecloser=symbology.SymbologyRecloser()
            symbologyRecloser.BuildSymbology(station=self)
            symbologyRegulator=symbology.SymbologyRegulator()
            symbologyRegulator.BuildSymbology(station=self)
            symbologySwitch=symbology.SymbologySwitch()
            symbologySwitch.BuildSymbology(station=self)
            return
        if(station):  #Span symbology must be rebuilt 1st, because some Symbology lines can be split in half by Station Symbology
	    Spans1=Span.objects.filter(StartStation=self)
	    Spans2=Span.objects.filter(EndStation=self)
	    Spans=[]
	    for span in Spans1:
	        Spans.append(span)
            for span in Spans2:
                Spans.append(span)
            for span in Spans:
                span.RebuildSymbology()
                span.FarStation(self).RebuildSymbology(RelatedSpanStationOnly=True)
        else:
            span=Span()
            span.RebuildSymbology(EntireMap=True)
        symbologyCutOut=symbology.SymbologyCutOut()
        symbologyCutOut.BuildSymbology(station=station)
        symbologyFeeder=symbology.SymbologyFeeder()
        symbologyFeeder.BuildSymbology(station=station)
        symbologyLight=symbology.SymbologyLight()
        symbologyLight.BuildSymbology(station=station)
        symbologyPoleJointUse=symbology.SymbologyPoleJointUse()
        symbologyPoleJointUse.BuildSymbology(station=station)
        symbologyPoleTreatment=symbology.SymbologyPoleTreatment()
        symbologyPoleTreatment.BuildSymbology(station=station)
        symbologyNonProtectingAssembly=symbology.SymbologyNonProtectingAssembly()
        symbologyNonProtectingAssembly.BuildSymbology(station=station)
        symbologyMeter=symbology.SymbologyMeter()
        symbologyMeter.BuildSymbology(station=station)
        symbologyOpenPoint=symbology.SymbologyOpenPoint()
        symbologyOpenPoint.BuildSymbology(station=station)
        symbologyTransformer=symbology.SymbologyTransformer()
        symbologyTransformer.BuildSymbology(station=station)
        symbologyPole=symbology.SymbologyPole()
        symbologyPole.BuildSymbology(station=station)
        symbologyRecloser=symbology.SymbologyRecloser()
        symbologyRecloser.BuildSymbology(station=station)
        symbologyRegulator=symbology.SymbologyRegulator()
        symbologyRegulator.BuildSymbology(station=station)
        symbologyStakerWorkOrderStation=symbology.SymbologyStakerWorkOrderStation()
        symbologyStakerWorkOrderStation.BuildSymbology(station=station)
        if(station):
            self.UpdateSymbology()
        else:
            Stations=Station.objects.all()
            for i in Stations:
                i.UpdateSymbology()
        symbologySubstation=symbology.SymbologySubstation()
        symbologySubstation.BuildSymbology(station=station)
        symbologySwitch=symbology.SymbologySwitch()
        symbologySwitch.BuildSymbology(station=station)
        symbologyURDMarker=symbology.SymbologyURDMarker()
        symbologyURDMarker.BuildSymbology(station=station)
        symbologyVault=symbology.SymbologyVault()
        symbologyVault.BuildSymbology(station=station)
    def Move(self, dx, dy):
        if(not dx):
            dx = 0
        if(not dy):
            dy = 0
        OriginalX=self.Point.x
        OriginalY=self.Point.y
	NewPoint=Point(x=self.Point.x, y=self.Point.y, srid=self.Point.srid)
	NewPoint.x = NewPoint.x + dx
	NewPoint.y = NewPoint.y + dy
	if(Station.objects.filter(Point__distance_lte=(NewPoint, 1 * djangoproject.settings.COOPGISDistanceMultiplier))):  
            dx = 0
            dy = 0  
        self.Point.x=self.Point.x + dx
        self.Point.y=self.Point.y + dy
        self.save()
        StartStationSpans=Span.objects.filter(StartStation=self)
        for i in StartStationSpans:
            i.FixLine()
        EndStationSpans=Span.objects.filter(EndStation=self)
        for i in EndStationSpans:
            i.FixLine()
        self.RebuildSymbology()
	return ((OriginalX - self.Point.x), (OriginalY - self.Point.y))
    def OKToDelete(self):
	if(Span.objects.filter(StartStation=self)):
            return False
        if(Span.objects.filter(EndStation=self)):
            return False
        if(compatibleunit.Assembly.objects.filter(Station=self)):
            return False
	return True
    def GetLengthOfAllSpans(SpansAlreadyInLength):
        #If here, there is a URDMarker at the current Station, so want to get the length of all connected spans, unless they are in SpansAlreadyInLength list
        Spans1=Span.objects.filter(StartStation=self)
        for i in Spans1:
            if(not i in SpansAlreadyInLength):
                CurrentLength = CurrentLength + i.GetLength(SpansAlreadyInLength)
        Spans2=Span.objects.filter(EndStation=self)
        for i in Spans2:   
            if(not i in SpansAlreadyInLength):
                CurrentLength = CurrentLength + i.GetLength(SpansAlreadyInLength)
        return CurrentLength
    def GetNearbySpans(self):
        Spans1=Span.objects.filter(StartStation=self)
        Spans2=Span.objects.filter(EndStation=self)
        SpanList=[]
        for span in Spans1:
            SpanList.append(span)
        for span in Spans2:
            SpanList.append(span)
        return SpanList
    def GetCircuitNumbers(self):
        """GetCircuitNumbers returns a List of all circuit numbers in a station and connected spans"""
        StationAssemblies=compatibleunit.Assembly.objects.filter(Station=self)
        CircuitNumbers=[]
        for assembly in StationAssemblies:
            if(not assembly.CircuitNumber in CircuitNumbers):
                CircuitNumbers.append(assembly.CircuitNumber)
        NearbySpans=self.GetNearbySpans()
        for span in NearbySpans:
            TempCircuitNumbers=span.GetCircuitNumbers()
            for circuitNumber in TempCircuitNumbers:
                if(not circuitNumber in CircuitNumbers):
                    CircuitNumbers.append(circuitNumber)
        CircuitNumbers.sort()
        return CircuitNumbers        
    def DeleteURDMarkerStation(self):
        """Deletes a URD Marker or empty Station off of the Server, will not delete otherwise,
           also deletes associated spans"""
        if(not djangoproject.settings.COOPGISServerIndicator):
            return False
        StationAssemblies=compatibleunit.Assembly.objects.filter(Station=self)
        for i in StationAssemblies:
            if(not i.CompatibleUnit.URDMarkerIndicator):
                return False
        for i in StationAssemblies:
            i.delete()
        self.RebuildSymbology()
        spans1=Span.objects.filter(StartStation=self)
        spans2=Span.objects.filter(EndStation=self)
        spans=[]
        for span in spans1:
             spans.append(span)
        for span in spans2:
            spans.append(span)
        for span in spans:
            SpanAssemblies=compatibleunit.Assembly.objects.filter(Span=span)
            for assembly in SpanAssemblies:
                assembly.delete()
            span.RebuildSymbology()
            span.delete()
        self.delete()        
    def GetNearbyStationInfo(self):
        AssemblyList=[]
        distance = Distance(**{application.COOPGISConfig.GetShortDistanceUnit():application.COOPGISConfig.GetMaximumDistanceToFindNearbyStations()})
        NearbyStations=Station.objects.filter(Point__distance_lte=(self.Point, distance)).distance(self.Point).order_by('distance')
        NearbyStations = NearbyStations[:5] #take the 5 closest nearby stations

        NearbyStationStrings=[]
        for i in NearbyStations:
            NearbyStationStrings.append([getattr(i.distance, application.COOPGISConfig.GetShortDistanceUnit()), i.StringDetailed()])
        for i in NearbyStationStrings:
            AssemblyList.append([int(round(i[0])), str(i[1])])
        AssemblyList.sort()
        for i in AssemblyList:
            i[0] = str(i[0]) + ' ' + application.COOPGISConfig.GetShortDistanceUnit()
        DisplayAssemblyList=[]
        for i in AssemblyList:
            DisplayAssemblyList.append(i[0])
            DisplayAssemblyList.append(i[1])
        AssemblyList=DisplayAssemblyList   
        return AssemblyList
    def GetNearbySpanInfo(self):
        AssemblyList=[]
        distance = Distance(**{application.COOPGISConfig.GetShortDistanceUnit():application.COOPGISConfig.GetMaximumDistanceToFindNearbyStations()})

        NearbySpans=Span.objects.filter(Line__distance_lte=(self.Point, distance)).distance(self.Point).order_by('distance')
        NearbySpans = NearbySpans[:5]
        NearbySpanStrings=[]
        for i in NearbySpans:
            NearbySpanStrings.append([getattr(i.distance, application.COOPGISConfig.GetShortDistanceUnit()), i.StringDetailed()])
        for i in NearbySpanStrings:
            AssemblyList.append([int(round(i[0])), str(i[1])])
        AssemblyList.sort()
        for i in AssemblyList:
            i[0] = str(i[0]) + ' ' + application.COOPGISConfig.GetShortDistanceUnit()
        DisplayAssemblyList=[]
        for i in AssemblyList:
            DisplayAssemblyList.append(i[0])
            DisplayAssemblyList.append(i[1])
        AssemblyList=DisplayAssemblyList   
        return AssemblyList
    def GetTagNumbers(self):
        Assemblies=compatibleunit.Assembly.objects.filter(Station=self)
        TagNumbers=[]
        for i in Assemblies:
            if(i.TagNumber):
                TagNumbers.append(i.TagNumber)
        return TagNumbers
    def GetPhaseCode(self, IncludeNeutral=True, CircuitNumber='ANY'):
        APhaseAssemblies=compatibleunit.Assembly.objects.filter(Station=self).filter(PhaseAIndicator=True)
        BPhaseAssemblies=compatibleunit.Assembly.objects.filter(Station=self).filter(PhaseBIndicator=True)
        CPhaseAssemblies=compatibleunit.Assembly.objects.filter(Station=self).filter(PhaseCIndicator=True)
        NPhaseAssemblies=compatibleunit.Assembly.objects.filter(Station=self).filter(PhaseNeutralIndicator=True)
        if(not CircuitNumber == 'ANY'):
            APhaseAssemblies=APhaseAssemblies.filter(CircuitNumber=CircuitNumber)
            BPhaseAssemblies=BPhaseAssemblies.filter(CircuitNumber=CircuitNumber)
            CPhaseAssemblies=CPhaseAssemblies.filter(CircuitNumber=CircuitNumber)
            NPhaseAssemblies=NPhaseAssemblies.filter(CircuitNumber=CircuitNumber)

        Result=''
        if(APhaseAssemblies):
            Result = Result + 'A'
        if(BPhaseAssemblies):
            Result = Result + 'B'
        if(CPhaseAssemblies):
            Result = Result + 'C'
        if(NPhaseAssemblies and IncludeNeutral):
            Result = Result + 'N'
        return Result
    def GetIndexWhenReverseSorted(self):
        Objects=Station.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()





class Span(models.Model):
    """Spans connect two stations.  They hold electrical line features"""
    StartStation=models.ForeignKey('Station', related_name="SpanStartPoint", on_delete=models.PROTECT)
    EndStation=models.ForeignKey('Station', related_name="SpanEndPoint", on_delete=models.PROTECT)
    Line=models.LineStringField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    JointTrenchIndicator=models.BooleanField()
    Description=models.TextField()
    ResidesOnServerIndicator=models.NullBooleanField(blank=True, null=True)
    CreateCommand=models.ForeignKey('Command', blank=True, null=True, on_delete=models.SET_NULL)
    TapIndicator=models.NullBooleanField(null=True, blank=True)
    SymbologyCompatibleUnits=models.TextField(blank=True, null=True, db_column='symbologycompatibleunits')
    SymbologyInstallIndicator=models.NullBooleanField(blank=True, null=True, db_column='symbologyinstallindicator')
    SymbologyExistingIndicator=models.NullBooleanField(blank=True, null=True, db_column='symbologyexistingindicator')
    SymbologyRemoveIndicator=models.NullBooleanField(blank=True, null=True, db_column='symbologyremoveindicator')
    StakerStopTraceIndicator=models.NullBooleanField(blank=True, null=True, db_column='stakerstoptraceindicator')
    
    #CompatibleUnitOneName, CompatibleUnitOneNumber, CompatibleUnitTwoName, and CompatibleUnitTwoNumber allow for quick maps of where various compatibleunits are installed at
    CompatibleUnitOneName=models.TextField(db_column='compatibleunitonename', null=True, blank=True) 
    CompatibleUnitOneNumber=models.IntegerField(db_column='compatibleunitonenumber', null=True, blank=True)
    CompatibleUnitTwoName=models.TextField(db_column='compatibleunittwoname', null=True, blank=True) 
    CompatibleUnitTwoNumber=models.IntegerField(db_column='compatibleunittwonumber', null=True, blank=True)

    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisspan'
        app_label='djangoproject'
    @staticmethod
    def GetOrCreate(StartStation, EndStation, Line=None, JointTrenchIndicator=False, Description='', TapIndicator=False, CreateCommand=None,
                    StakerStopTraceIndicator='Default'):
        """If Line is None, then use an existing Line or create a new straight line
        between the points, otherwise, match the line and use it"""
        #To keep all stations from the same points in the same start-end order...
        #swap them, the one with the lowest .x is 1st (or lowest y if x is equal
        if(StartStation.Point.x > EndStation.Point.x or (StartStation.Point.x == EndStation.Point.x)
           and (StartStation.Point.y > EndStation.Point.y)):
            Temp=StartStation
            StartStation=EndStation
            EndStation=Temp
        #Require that a Span connect 2 different stations
        if(StartStation.Point.x == EndStation.Point.x and StartStation.Point.y == EndStation.Point.y):
            StartAndEndStationsAreSame=Exception()  
            raise StartAndEndStationsAreSame
        #Check to make sure the Line includes the StartStation as its starting point and the EndStation as its ending point
        LineCoordinates=[]
        if(LineCoordinates):  #Create the LineObject from the Coordinate List
            Line=LineString(LineCoordinates)  
        if(Line):  #See if the Span already exists
            try:
                New=Span.objects.filter(StartStation=StartStation).filter(EndStation=EndStation, Line=Line)  
                return New[0]
            except:
                pass    
        else:
            try:  #Could be multiple matching spans
		New=Span.objects.filter(StartStation=StartStation).filter(EndStation=EndStation)
                return New[0]
            except:
                pass
        #Now create the New Span since it does not already exist
        #Start and End Stations are in the correct Order, and the Line has been validated to start with
        #The Start Station Point and End at the End Station Point
        #The 1st Coordinate of the Line (if it exists) is at the start station, the last coordinate is at the end station
        New=Span()
        New.StartStation=StartStation
        New.EndStation=EndStation
        New.JointTrenchIndicator=JointTrenchIndicator
        New.TapIndicator=TapIndicator
        if(not StakerStopTraceIndicator == 'Default'):
            New.StakerStopTraceIndicator=StakerStopTraceIndicator
        LineList=[]
        if(Line):
            for i in Line.coords:
                LineList.append(i)
        else:
            LineList.append(StartStation.Point)
            LineList.append(EndStation.Point)
        New.Line=LineString(LineList)
        New.Description=Description
        New.ResidesOnServerIndicator=djangoproject.settings.COOPGISServerIndicator
        New.CreateCommand=CreateCommand
        New.save()
        New.RebuildSymbology()
        return New
    def FarStation(self, CloseStation):
        if(self.StartStation == CloseStation):
            return self.EndStation
        if(self.EndStation == CloseStation):
            return self.StartStation
        return None
    def StringDetailed(self):
        Assemblies=compatibleunit.Assembly.objects.all().filter(Span=self)
        if(not '__len__' in (dir(Assemblies))):
            Assemblies = [Assemblies]
        StringList=[]
	StringList.append('#' + str(self.id))
        grid=Grid.objects.all().filter(Border__contains=self.Line).filter(SubGridIndicator=False)
	
        try:
            StringList.append(str(grid[0]))
	except IndexError:
            pass 
        NearbyRoads=Road.objects.filter(Line__distance_lte=(self.Line, 9000 * djangoproject.settings.COOPGISDistanceMultiplier))
	ClosestRoad=''
	ClosestDistance=9000 * djangoproject.settings.COOPGISDistanceMultiplier
	for i in NearbyRoads:
	   if(self.Line.distance(i.Line) < ClosestDistance):
	       ClosestDistance=self.Line.distance(i.Line)
               ClosestRoad=i.Name
        try:
            StringList.append(str(int(ClosestDistance)) + " feet away:  " + ClosestRoad)
        except:
            pass
        for i in Assemblies:
            StringList.append(i.StringDetailed())
        return ', '.join(StringList)
    def UpdateSymbology(self):
        Assemblies=compatibleunit.Assembly.objects.filter(Span=self).exclude(InstallStatus__Name='Install')
        CompatibleUnitList=self.SymbologyCombineLikeSpanAssemblies(Assemblies)
        InstallAssemblies=compatibleunit.Assembly.objects.filter(Span=self).filter(InstallStatus__Name='Install')
        InstallCompatibleUnitList=self.SymbologyCombineLikeSpanAssemblies(InstallAssemblies, InstallIndicator=True)
        for i in InstallCompatibleUnitList:
            i = '(IN)' + i
        if(InstallCompatibleUnitList and CompatibleUnitList):
            InstallCompatibleUnitList[-1]=InstallCompatibleUnitList[-1] + ','
        self.SymbologyCompatibleUnits=str(self.id) + ":  " + ','.join(InstallCompatibleUnitList) + ','.join(CompatibleUnitList)
        
        if(compatibleunit.Assembly.objects.filter(Span=self).filter(InstallStatus__Name='Install')):
            self.SymbologyInstallIndicator=True
        else:
            self.SymbologyInstallIndicator=False
        if(compatibleunit.Assembly.objects.filter(Span=self).filter(InstallStatus__Name='Existing')):
            self.SymbologyExistingIndicator=True
        else:
            self.SymbologyExistingIndicator=False
        if(compatibleunit.Assembly.objects.filter(Span=self).filter(InstallStatus__Name='Remove')):
            self.SymbologyRemoveIndicator=True
        else:
            self.SymbologyRemoveIndicator=False
        self.save()
    def SymbologyCombineLikeSpanAssemblies(self, AssemblyList, InstallIndicator=False):
        CombinedAssemblyList=[]
        CombinationsAdded=[]
        for i in range(0, len(AssemblyList)):
            CountOfCurrentAssembly=0
            for j in range(0, len(AssemblyList)):
                if(AssemblyList[i].CompatibleUnit.Name == AssemblyList[j].CompatibleUnit.Name):
                    CountOfCurrentAssembly = CountOfCurrentAssembly + 1
            if(not ('Assembly:  ' + str(AssemblyList[i]) in CombinationsAdded)):
                CurrentAssemblyName=AssemblyList[i].CompatibleUnit.Name
                if(InstallIndicator):
                    CurrentAssemblies=compatibleunit.Assembly.objects.filter(Span=self).filter(CompatibleUnit__Name=CurrentAssemblyName).filter(InstallStatus__Name='Install')
                else:
                    CurrentAssemblies=compatibleunit.Assembly.objects.filter(Span=self).filter(CompatibleUnit__Name=CurrentAssemblyName).exclude(InstallStatus__Name='Install')
                PhaseCodeString=' [' + CurrentAssemblies[0].GetSumOfPhaseCodes(CurrentAssemblies) + ']'
                if(PhaseCodeString == ' []'):
                    PhaseCodeString = ''
                if(CountOfCurrentAssembly == 1):
                    CombinedAssemblyList.append(str(AssemblyList[i]) + PhaseCodeString)
                else:
                    CombinedAssemblyList.append(str(CountOfCurrentAssembly) + '-' + str(AssemblyList[i]) + PhaseCodeString)
                CombinationsAdded.append('Assembly:  ' + str(AssemblyList[i]))
        return CombinedAssemblyList
    def RebuildSymbology(self, EntireMap=False):
        if(EntireMap):
            span=None
        else:
            span=self
        symbologyPrimaryLine=symbology.SymbologyPrimaryLine()
        symbologyPrimaryLine.BuildSymbology(span=span)
        symbologySecondaryLine=symbology.SymbologySecondaryLine()
        symbologySecondaryLine.BuildSymbology(span=span)
        symbologyProtectedSpan=symbology.SymbologyProtectedSpan()
        symbologyProtectedSpan.BuildSymbology(span=span)
        symbologySpanGuy=symbology.SymbologySpanGuy()
        symbologySpanGuy.BuildSymbology(span=span)
        symbologyStakerWorkOrderSpan=symbology.SymbologyStakerWorkOrderSpan()
        symbologyStakerWorkOrderSpan.BuildSymbology(span=span)
        if(span):
            self.UpdateSymbology()
        else:
            Spans=Span.objects.all()
            for i in Spans:
                i.UpdateSymbology()
    def FixLine(self):
        """Rebuilds the Line Symbology and swaps the start and end stations if needed, such as when stations are moved.
        Also splits a line into its component segments, with a station at each former vertex"""
        #To keep all stations from the same points in the same start-end order...
        #swap them, the one with the lowest .x is 1st (or lowest y if x is equal
        if(self.StartStation.Point.x > self.EndStation.Point.x or (self.StartStation.Point.x == self.EndStation.Point.x)
           and (self.StartStation.Point.y > self.EndStation.Point.y)):
            Temp=self.StartStation
            self.StartStation=self.EndStation
            self.EndStation=Temp
            #Also need to reverse the line
            ReversedLineCoordinates=[]
            for coordinate in self.Line:
                ReversedLineCoordinates.insert(0, coordinate)
            self.Line=LineString(ReversedLineCoordinates)
	    self.save()
        #Check to make sure the Line includes the StartStation as its starting point and the EndStation as its ending point
        LineCoordinates=[]
        for coordinate in self.Line:
            LineCoordinates.append(coordinate)
        LineCoordinates[0]=self.StartStation.Point
        LineCoordinates[-1]=self.EndStation.Point
        self.Line=LineString(LineCoordinates)
        self.save()
	self.RebuildSymbology()
        if(len(LineCoordinates) > 2): #Then there is a corner, eliminate it
            print "IN FIX LINE REMOVE CORNERS."
            #First Get or Create a station at the Vertex to be eliminated
            station=Station()
            StartPoint=Point(x=LineCoordinates[1][0], y=LineCoordinates[1][1], srid=self.Line.srid)
            StartDistance=.8 
            MaximumDistance=1
            Step=.1
            station=station.GetOrCreateClosestStation(StartPoint, StartDistance, MaximumDistance, Step)
            span=Span()
            if(self.EndStation == station):  #Meaning the corner matches the start station
                 NewSelfLineCoordinates=[]
                 NewSelfLineCoordinates.append(LineCoordinates[0])
                 for i in LineCoordinates[2:]:
                      NewSelfLineCoordinates.append(i)
                 self.Line=LineString(NewSelfLineCoordinates)
                 self.save()
            else:
                NewSpan=span.GetOrCreate(station, self.EndStation, LineString(LineCoordinates[1:]))
                AssembliesToCopy=compatibleunit.Assembly.objects.filter(Span=self)
                for i in AssembliesToCopy:
                    assembly=compatibleunit.Assembly()
                    assembly.GetOrCreate(CompatibleUnit=i.CompatibleUnit, Quantity=i.Quantity, Station=None, Span=NewSpan,
                        Rotation=i.Rotation,
                        PhaseAIndicator=i.PhaseAIndicator, PhaseBIndicator=i.PhaseBIndicator, PhaseCIndicator=i.PhaseCIndicator,
                        PhaseNeutralIndicator=i.PhaseNeutralIndicator,
                        CircuitNumber=i.CircuitNumber, assemblyOwner=i.AssemblyOwner,
                        PutIntoServiceDate=i.PutIntoServiceDate,
                        TagNumber=i.TagNumber, Description=i.Description, Manufacturer=i.Manufacturer,
                        OverHeadIndicator=i.OverHeadIndicator, UndergroundIndicator=i.UndergroundIndicator,
                        PrimaryIndicator=i.PrimaryIndicator, SecondaryIndicator=i.SecondaryIndicator, ServiceIndicator=i.ServiceIndicator, 
                        ConductorPlacementStartStation=i.ConductorPlacementStartStation, ConductorPlacementEndStation=i.ConductorPlacementEndStation,
                        ActualVoltage=i.ActualVoltage,
                        TransformerPrimaryWinding=i.TransformerPrimaryWinding, TransformerSecondaryWinding=i.TransformerSecondaryWinding,
                        RecloserMaximumContinousAmp=i.RecloserMaximumContinousAmp, RecloserMaximumIntermittentAmp=i.RecloserMaximumIntermittentAmp,
                        RecloserLinkRating=i.RecloserLinkRating,
                        LightLampType=i.LightLampType, LightFixtureType=i.LightFixtureType,
                        PoleRightOfWayStatus=i.PoleRightOfWayStatus, PoleLightIndicator=i.PoleLightIndicator,
                        PoleGuyIndicator=i.PoleGuyIndicator, PoleStubIndicator=i.PoleStubIndicator, PoleMeterIndicator=i.PoleMeterIndicator,
                        RecloserType=i.RecloserType, RecloserTripSetting=i.RecloserTripSetting,
                        RegulatorCurrentTransformerRating=i.RegulatorCurrentTransformerRating, RegulatorPanelType=i.RegulatorPanelType,
                        RegulatorSetting=i.RegulatorSetting,
                        CutOutFuse=i.CutOutFuse,
                        SubstationName=i.SubstationName, SubstationSourceRegulatedIndicator=i.SubstationSourceRegulatedIndicator,
                        SubstationLoadConnection=i.SubstationLoadConnection,
                        OpenIndicator=i.OpenIndicator, 
                        TransformerCompletelySelfProtectedIndicator=i.TransformerCompletelySelfProtectedIndicator,
                        TransformerSecondaryHighVoltage=i.TransformerSecondaryHighVoltage,
                        TransformerSecondaryLowVoltage=i.TransformerSecondaryLowVoltage,
                        MeterDescription=i.MeterDescription, MeterServiceType=i.MeterServiceType,
                        MeterDCSINumber=i.MeterDCSINumber, MeterNumber=i.MeterNumber, meterForm=i.MeterForm,
                        MeterOnPoleIndicator=i.MeterOnPoleIndicator, 
                        MeterActiveIndicator=i.MeterActiveIndicator, SubstationVoltage=i.SubstationVoltage)
                self.EndStation=station
                self.Line=LineString([LineCoordinates[0], LineCoordinates[1]])
                self.save()
                self.RebuildSymbology()
		NewSpan.save()
		NewSpan.RebuildSymbology()            
    def OKToDelete(self):
        if(compatibleunit.Assembly.objects.filter(Span=self)):
	    return False
	else:
	    return True        
    def GetAllMatching(self, Station1, Station2=None):
        if(Station2):
            Spans1=Span.objects.filter(StartStation=Station1).filter(EndStation=Station2)
            Spans2=Span.objects.filter(StartStation=Station2).filter(EndStation=Station1)
        else:
            Spans1=Span.objects.filter(StartStation=Station1)
            Spans2=Span.objects.filter(EndStation=Station1)
        AllMatching=[]
        for i in Spans1:
            AllMatching.append(i)
        for i in Spans2:
            AllMatching.append(i)
        return AllMatching
    def GetLength(self, SpansAlreadyInLength=[]):
        SpansAlreadyInLength.append(self)
        CurrentLength=0
        CurrentLength=CurrentLength+self.Line.length
        try:
            Marker1=compatibleunit.Assembly.objects.filter(Station=self.StartStation).filter(CompatibleUnit__URDMarkerIndicator=True)[0]
            CurrentLength=CurrentLength + Marker1.Station.GetLengthOfAllSpans(SpansAlreadyInLength) 
        except:
            pass
        try:
            Marker2=compatibleunit.Assembly.objects.filter(Station=self.EndStation).filter(CompatibleUnit__URDMarkerIndicator=True)[0]
            CurrentLength=CurrentLength + Marker2.Station.GetLengthOfAllSpans(SpansAlreadyInLength) 
        except:
            pass
        return CurrentLength
    def GetPhaseCode(self, IncludeNeutral=True, CircuitNumber='ANY'):
        APhaseAssemblies=compatibleunit.Assembly.objects.filter(Span=self).filter(PhaseAIndicator=True)
        BPhaseAssemblies=compatibleunit.Assembly.objects.filter(Span=self).filter(PhaseBIndicator=True)
        CPhaseAssemblies=compatibleunit.Assembly.objects.filter(Span=self).filter(PhaseCIndicator=True)
        NPhaseAssemblies=compatibleunit.Assembly.objects.filter(Span=self).filter(PhaseNeutralIndicator=True)
        if(not CircuitNumber == 'ANY'):
            APhaseAssemblies=APhaseAssemblies.filter(CircuitNumber=CircuitNumber)
            BPhaseAssemblies=BPhaseAssemblies.filter(CircuitNumber=CircuitNumber)
            CPhaseAssemblies=CPhaseAssemblies.filter(CircuitNumber=CircuitNumber)
            NPhaseAssemblies=NPhaseAssemblies.filter(CircuitNumber=CircuitNumber)

        Result=''
        if(APhaseAssemblies):
            Result = Result + 'A'
        if(BPhaseAssemblies):
            Result = Result + 'B'
        if(CPhaseAssemblies):
            Result = Result + 'C'
        if(NPhaseAssemblies and IncludeNeutral):
            Result = Result + 'N'
        return Result
    def GetCircuitNumbers(self):
        """GetCircuitNumbers returns a List of all circuit numbers in a span"""
        SpanAssemblies=compatibleunit.Assembly.objects.filter(Span=self)
        CircuitNumbers=[]
        for assembly in SpanAssemblies:
            if(not assembly.CircuitNumber in CircuitNumbers):
                CircuitNumbers.append(assembly.CircuitNumber)
        CircuitNumbers.sort()
        return CircuitNumbers
    def SplitSpanInHalf(self, OriginalSpan, UserNameOrIPAddress, stakerWorkOrder=None):
        import command
        if(OriginalSpan.Line.length < 10):
            return False  #Do not split spans shorter than 10 feet
        MidPointX=(OriginalSpan.StartStation.Point.x + OriginalSpan.EndStation.Point.x) / 2
        MidPointY=(OriginalSpan.StartStation.Point.y + OriginalSpan.EndStation.Point.y) / 2
        NewMiddlePoint=Point(MidPointX, MidPointY, srid=djangoproject.settings.COOPGISSRID)
        temp=command.Command()
        temp=temp.Create(Name='CreateStation', StartPoint=NewMiddlePoint, CommandUserName=UserNameOrIPAddress, CommandReadyToProcessIndicator=True)
        NewMiddleStation=temp.Process()
        #A Station in the Middle of the Span has been created
        #Now, Need to create a list of assemblies that will need to be added back to the two new spans
        OldAssemblies=compatibleunit.Assembly.objects.filter(Span=OriginalSpan)
        TempAssemblies=[]
        for i in OldAssemblies:
            TempRow=[]
            TempRow.append(i.CompatibleUnit.Name)
            TempRow.append(i.Span.StartStation.Point)
            TempRow.append(NewMiddleStation.Point)
            TempRow.append(LineString(i.Span.StartStation.Point, NewMiddleStation.Point, srid=djangoproject.settings.COOPGISSRID))
            TempRow.append(i.PhaseAIndicator)
            TempRow.append(i.PhaseBIndicator)
            TempRow.append(i.PhaseCIndicator)
            TempRow.append(i.PhaseNeutralIndicator)
            TempRow.append(i.CircuitNumber)
            TempRow.append(i.PrimaryIndicator)
            #Flip the Secondary and Service Indicators as needed
            if(i.SecondaryIndicator):  #Flip the Secondary Indicator if the new compatible unit will be next to a meter and secondaryindicator is true
                if(compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                    TempRow.append(False) #Secondary Indicator
                else:
                    TempRow.append(True) #Secondary Indicator
            elif(i.ServiceIndicator):  #else if it has a Service Indicator but is not by a meter, flip the Secondary Indicator
               if(not compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                   TempRow.append(True) #Secondary Indicator
               else:
                   TempRow.append(False) #Secondary Indicator
            else:
                TempRow.append(i.SecondaryIndicator)
    
            if(i.SecondaryIndicator and not i.ServiceIndicator):  #Flip the Service Indicator if the new compatible unit will be next to a meter and is Secondary
                if(compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                    TempRow.append(True) #Service Indicator    
                else:    
                    TempRow.append(False) #Service Indicator
            elif(i.ServiceIndicator):  #else if it has a Service Indicator but is not by a meter, flip it to false
               if(not compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                   TempRow.append(False) #Service Indicator
               else:
                   TempRow.append(True) #Service Indicator
            else:
                TempRow.append(i.ServiceIndicator)
            #End Flipping of Secondary and Service Indicators
            TempRow.append(UserNameOrIPAddress)
            TempRow.append(True)
            TempRow.append(str(i.InstallStatus.Name))
            TempRow.append(i.IdleIndicator)
            TempRow.append(str(stakerWorkOrder.Name))
            TempAssemblies.append(TempRow)
        for i in OldAssemblies:
            TempRow=[]
            TempRow.append(i.CompatibleUnit.Name)
            TempRow.append(NewMiddleStation.Point)
            TempRow.append(i.Span.EndStation.Point)
            TempRow.append(LineString(NewMiddleStation.Point, i.Span.EndStation.Point, srid=djangoproject.settings.COOPGISSRID))
            TempRow.append(i.PhaseAIndicator)
            TempRow.append(i.PhaseBIndicator)
            TempRow.append(i.PhaseCIndicator)
            TempRow.append(i.PhaseNeutralIndicator)
            TempRow.append(i.CircuitNumber)
            TempRow.append(i.PrimaryIndicator)
            #Flip the Secondary and Service Indicators as needed
            if(i.SecondaryIndicator):  #Flip the Secondary Indicator if the new compatible unit will be next to a meter and secondaryindicator is true
                if(compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                    TempRow.append(False) #Secondary Indicator
                else:
                    TempRow.append(True) #Secondary Indicator
            elif(i.ServiceIndicator):  #else if it has a Service Indicator but is not by a meter, flip the Secondary Indicator
               if(not compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                   TempRow.append(True) #Secondary Indicator
               else:
                   TempRow.append(False) #Secondary Indicator
            else:
                TempRow.append(i.SecondaryIndicator)

            if(i.SecondaryIndicator and not i.ServiceIndicator):  #Flip the Service Indicator if the new compatible unit will be next to a meter and is Secondary
                if(compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                    TempRow.append(True) #Service Indicator
                else:
                    TempRow.append(False) #Service Indicator
            elif(i.ServiceIndicator):  #else if it has a Service Indicator but is not by a meter, flip it to false
               if(not compatibleunit.Assembly.objects.filter(Station=i.Span.StartStation).filter(CompatibleUnit__MeterIndicator=True)):
                   TempRow.append(False) #Service Indicator
               else:
                   TempRow.append(True) #Service Indicator
            else:
                TempRow.append(i.ServiceIndicator)
            #End Flipping of Secondary and Service Indicators
            TempRow.append(UserNameOrIPAddress)
            TempRow.append(True) #CommandReadyToProcessIndicator
            TempRow.append(str(i.InstallStatus.Name))
            TempRow.append(i.IdleIndicator)
            if(stakerWorkOrder):
                TempRow.append(str(stakerWorkOrder.Name))
            else:
                TempRow.append('None')
            TempAssemblies.append(TempRow)
        #Delete those assemblies using Commands
        for i in OldAssemblies:
            command.DeleteAssembly(i.id, UserNameOrIPAddress)
        #Delete the Original Span using a Command
        SpanJointTrenchIndicator=OriginalSpan.JointTrenchIndicator
        Line=fromstr(str(OriginalSpan.Line), srid=djangoproject.settings.COOPGISSRID)
        StartStation=OriginalSpan.StartStation
        EndStation=OriginalSpan.EndStation
        temp=command.Command()
        temp=temp.Create(Name='DeleteSpan', Line=Line, StartPoint=StartStation.Point, EndPoint=EndStation.Point, CommandUserName=UserNameOrIPAddress,
                              CommandReadyToProcessIndicator=True)
        temp.Process() 
        #Create a Span from OriginalStartStation to NewMiddleStation using a Command
        temp=command.Command()
        temp=temp.Create(Name='CreateSpan', StartPoint=StartStation.Point, EndPoint=NewMiddlePoint, 
                               JointTrenchIndicator=SpanJointTrenchIndicator, CommandUserName=UserNameOrIPAddress,
                               CommandReadyToProcessIndicator=True)
        temp.Process()
        #Create a Span from NewMiddleStation to OriginalEndStation using a Command
        temp=command.Command()
        temp=temp.Create(Name='CreateSpan', StartPoint=NewMiddlePoint, EndPoint=EndStation.Point, 
                               JointTrenchIndicator=SpanJointTrenchIndicator, CommandUserName=UserNameOrIPAddress,
                               CommandReadyToProcessIndicator=True)
        temp.Process()
        #Add all of the Assemblies back to them using Commands
        for i in TempAssemblies:
            temp=temp.Create(Name='CreateSpanAssembly', AssemblyName=i[0], StartPoint=i[1], EndPoint=i[2], Line=i[3], 
                                         PhaseAIndicator=i[4], PhaseBIndicator=i[5], PhaseCIndicator=i[6],
                                         PhaseNeutralIndicator=i[7], CircuitNumber=i[8],  
                                         PrimaryIndicator=i[9], SecondaryIndicator=i[10],ServiceIndicator=i[11],
                                         CommandUserName=i[12], CommandReadyToProcessIndicator=i[13], InstallStatus=i[14],
                                         IdleIndicator=i[15], StakerWorkOrderName=i[16])
            temp.Process()
        return 'Successfully Split the Span'
    def __unicode__(self):
        return str(self.id)


class State(models.Model):
    """State is a list of valid States in the COOP System (SC)"""
    Name=models.CharField(max_length=250)
    Description=models.TextField()
    Border=models.PolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisstate'
        app_label='djangoproject'
    def GetOrCreate(self, Name, Border, Description=''):
        try:
            New=State.objects.get(Name=Name)
            return New
        except:
            pass
        New=State()
        New.Name=Name
        New.Border=Border
        New.Description=Description
        New.save()
        return New

class County(models.Model):
    """County is a list of valid Counties in the COOP System"""
    Name=models.CharField(max_length=250)
    Description=models.TextField()
    Border=models.MultiPolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISGPSSRID)
    CISIdentifier=models.TextField(db_column='cisidentifier', unique=True, null=True, blank=True)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgiscounty'
        app_label='djangoproject'
    def GetOrCreate(self, Name, Border, Description=''):
        try:
            New=County.objects.get(Name=Name)
            return New
        except:
            pass
        New=County()
        New.Name=Name
        New.Border=Border
        New.Description=Description
        New.save()
        return New

class Water(models.Model):
    """Water Holds boundaries and names of bodies of water"""
    Name=models.CharField(max_length=250, null=True, blank=True, db_column='name')
    Description=models.TextField(null=True, blank=True, db_column='description')
    Border=models.PolygonField(null=True, blank=True, db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgiswater'
        app_label='djangoproject'
    def GetOrCreate(self, Name, Border, Description=''):
        try:
            New=Water.objects.get(Name=Name)
            return New
        except:
            pass
        New=Water()
        New.Name=Name
        New.Border=Border
        New.Description=Description
        New.save()
        return New

class ZipCode(models.Model):
    """ZipCode is a list of valid zip codes in the COOP System"""
    Name=models.CharField(max_length=250)
    Description=models.TextField()
    City=models.ForeignKey('City', on_delete=models.PROTECT)
    Border=models.PolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgiszipcode'
        app_label='djangoproject'
    def GetOrCreate(self, Name, City, Border, Description=''):
        try:
            New=ZipCode.objects.get(Name=Name)
            return New
        except:
            pass
        New=ZipCode()
        New.Name=Name
        New.City=City
        New.Border=Border
        New.Description=Description
        New.save()
        return New

class Road(models.Model):
    """Road is most/all of the area roads in the COOP System"""
    Name=models.CharField(db_column='name', max_length=250, null=True, blank=True)
    ShadowName=models.CharField(db_column='Name', max_length=250, null=True, blank=True) #Exists to export to a vendors db
    ShadowAlternateName=models.CharField(db_column='AlternateName', max_length=250, null=True, blank=True) #Exists to export to a vendords db
    Number=models.CharField(db_column='number', max_length=250, null=True, blank=True)
    InterstateIndicator=models.NullBooleanField(db_column='interstateindicator', null=True, blank=True)
    USHighwayIndicator=models.NullBooleanField(db_column='ushighwayindicator', null=True, blank=True)
    StateHighwayIndicator=models.NullBooleanField(db_column='statehighwayindicator', null=True, blank=True)
    MainRoadIndicator=models.NullBooleanField(db_column='mainroadindicator', null=True, blank=True)
    LeftFromAddress = models.CharField(db_column='leftfromaddress', max_length=250, null=True, blank=True)
    LeftToAddress = models.CharField(db_column='lefttoaddress', max_length=250, null=True, blank=True)
    RightFromAddress = models.CharField(db_column='rightfromaddress', max_length=250, null=True, blank=True)
    RightToAddress = models.CharField(db_column='righttoaddress', max_length=250, null=True, blank=True)
    ResidesOnServerIndicator=models.NullBooleanField(db_column='residesonserverindicator', null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    Line=models.LineStringField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    #OMS Provider requested a road type flag column of a single character to signify the type of road
    #'I' = Interstate
    #'U' = US Highway
    #'S' = State Highway
    #'M' = Main Road
    #'O' = Other/Secondary Road
    SymbologyRoadTypeFlag=models.CharField(db_column='symbologyroadtypeflag', max_length=1, null=True, blank=True)
    SelectionUserName=models.CharField(db_column='selectionusername', max_length=250, null=True, blank=True)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisroad'
        app_label='djangoproject'
    def __unicode__(self):
        return self.Name
    def GetPoint(self):
	return Line[0]
    def GetNearbyPole(self):
        RoadPoint=Point(self.Line[0], srid=djangoproject.settings.COOPGISSRID)
        CurrentDistance=500 * djangoproject.settings.COOPGISDistanceMultiplier
        MaximumDistance=22000 * djangoproject.settings.COOPGISDistanceMultiplier #~4 miles
        Step = 100
        while(CurrentDistance<MaximumDistance):
            Stations=Station.objects.filter(Point__distance_lte=(RoadPoint, CurrentDistance))
            for i in Stations:
                Temp = compatibleunit.Assembly.objects.filter(Station=i).filter(CompatibleUnit__PoleIndicator=True)
                if(Temp):
                    return Temp[0]
            CurrentDistance=CurrentDistance+Step
            Step = Step + CurrentDistance / 3 #increase the step size as you get further from the road
        return None
    def GetNearestRoadFromList(self, Point, Roads):
        Minimum = Roads[0]
        for road in Roads:
            if(Point.distance(road.Line) < Point.distance(Minimum.Line)):
                Minimum = road
        return Minimum
    def FindNearestRoad(self, Point):
        StartDistance=100
        MaxDistance=5280 * 25
        Step = 100
        CurrentDistance=StartDistance
        while(CurrentDistance < MaxDistance):
            Roads=Road.objects.filter(Line__distance_lte=(Point, CurrentDistance))
            if(Roads):
                return self.GetNearestRoadFromList(Point, Roads)
            CurrentDistance = CurrentDistance + Step
            Step = Step * 2
        return None
    def FindNearestIntersection(self, point):
        road=self.FindNearestRoad(point)
        if(not road):
            return "No Nearby Roads Found."
        Point1=Point(road.Line.x[0], road.Line.y[0], srid=road.Line.srid)
        Point2=Point(road.Line.x[len(road.Line.x)-1], road.Line.y[len(road.Line.y)-1], srid=road.Line.srid)
        Roads1=Road.objects.filter(Line__distance_lte=(Point1, 10))
        Roads2=Road.objects.filter(Line__distance_lte=(Point2, 10))
        #FIXME Should follow roads if no intersection is found until one is
        #FIXME Does not necessary return the absolute closest intersection (need to check points to see which one is closer)
        for i in Roads1:
            if(i.Name != road.Name):
                return 'Nearest Intersection:  ' + i.Name + ' and ' + road.Name
        for i in Roads2: 
            if(i.Name != road.Name):
                return 'Nearest Intersection:  ' + i.Name + ' and ' + road.Name 
        return 'Closest Road:  ' + road.Name
    def CalculateSymbology(self):
        if(self.InterstateIndicator):
            self.SymbologyRoadTypeFlag = 'I'
        elif(self.USHighwayIndicator):
            self.SymbologyRoadTypeFlag='U'
        elif(self.MainRoadIndicator):
            self.SymbologyRoadTypeFlag='M'
        else:
            self.SymbologyRoadTypeFlag='O'
        self.save()
    def ClearSelection(self, UserName):
        Roads=Road.objects.filter(SelectionUserName=UserName)
        for road in Roads:
            road.SelectionUserName=''
            road.save()
    def GetIndexWhenReverseSorted(self):
        Objects=Road.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()

class Grid(models.Model):
    """Grid is the traditional Map based grid of the System"""
    Name=models.CharField(max_length=250, db_column='name')
    Description=models.TextField(db_column='description')
    SubGridIndicator=models.BooleanField(db_column='subgridindicator')
    Border=models.PolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisgrid'
        app_label='djangoproject'
    def __unicode__(self):
        return self.Name

class City(models.Model):
    """City is a list of valid Cities in the COOP System"""
    Name=models.CharField(max_length=250)
    Description=models.TextField()
    Border=models.PolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgiscity'
        app_label='djangoproject'

class BoardDistrict(models.Model):
    """BoardDistricts are polygons within the COOP System"""
    Name=models.CharField(max_length=250, db_column='name')
    Description=models.TextField()
    Polygon=models.PolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    ResidesOnServerIndicator=models.NullBooleanField(null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    CISIdentifier=models.TextField(db_column='cisidentifier', unique=True, null=True, blank=True)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisboarddistrict'
        app_label='djangoproject'
    def GetNumberOfMeters(self):
        Stations=Station.objects.filter(Point__within=self.Polygon)
        MeterCount=0
        for station in Stations:
            MeterCount=MeterCount + compatibleunit.Assembly.objects.filter(Station=station).filter(CompatibleUnit__MeterIndicator=True).count()
        return MeterCount
    def GetIndexWhenReverseSorted(self):
        Objects=BoardDistrict.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()


class CountyParcelLexington(models.Model):
    Utility=models.TextField(db_column='utility')
    TMS=models.TextField(db_column='tms')
    Polygon=models.MultiPolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    objects=models.GeoManager()
    class Meta:
        db_table=u'countyparcellexington'
        app_label='djangoproject'

class BoardDistrictPoint(models.Model):
    """BoardDistrictPoints are points that represent a Board District within a BoardDistrictEdge"""
    Name=models.CharField(max_length=250, db_column='name')
    Description=models.TextField()
    Point=models.PointField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    ResidesOnServerIndicator=models.NullBooleanField(null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisboarddistrictpoint'
        app_label='djangoproject'
    def GetNumberOfMeters(self):
        return 'Not Implemented Yet'
    def GetIndexWhenReverseSorted(self):
        Objects=BoardDistrictPoint.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()

class BoardDistrictEdge(models.Model):
    """BoardDistrictEdge are Lines that represent the borders of Board Districts"""
    Line=models.LineStringField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    ResidesOnServerIndicator=models.NullBooleanField(null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisboarddistrictedge'
        app_label='djangoproject'
    def GetIndexWhenReverseSorted(self):
        Objects=BoardDistrictEdge.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()


class CensusEdge(models.Model):
    StateFIPSCode = models.CharField(db_column='statefp', max_length=2, null=True)
    CountyFIPSCode = models.CharField(db_column='countyfp', max_length=3, null=True)
    PermanentEdgeID = models.TextField(db_column='tlid', null=True) # This field type is a guess.
    PermanentLeftFaceEdgeID = models.TextField(db_column='tfidl', null=True) # This field type is a guess.
    PermanentRightFaceEdgeID = models.TextField(db_column='tfidr', null=True) # This field type is a guess.
    TIGERFeatureClassCode = models.CharField(db_column='mtfcc', max_length=5, null=True)
    Name = models.CharField(db_column='fullname', max_length=100, null=True)
    SpatialMetadataidentifier = models.CharField(db_column='smid', max_length=22, null=True)
    LeftFromAddress = models.CharField(db_column='lfromadd', max_length=12, null=True)
    LeftToAddress = models.CharField(db_column='ltoadd', max_length=12, null=True)
    RightFromAddress = models.CharField(db_column='rfromadd', max_length=12, null=True)
    RightToAddress = models.CharField(db_column='rtoadd', max_length=12, null=True)
    ZipLeft = models.CharField(db_column='zipl', max_length=5, null=True)
    ZipRight = models.CharField(db_column='zipr', max_length=5, null=True)
    FeatureClassCode = models.CharField(db_column='featcat', max_length=1, null=True)
    WaterFlag = models.CharField(db_column='hydroflg', max_length=1, null=True)
    RailFlag = models.CharField(db_column='railflg', max_length=1, null=True)
    RoadFlag = models.CharField(db_column='roadflg', max_length=1, null=True)
    OtherFlag = models.CharField(db_column='olfflg', max_length=1, null=True)
    SpecialPassageFlag = models.CharField(db_column='passflg', max_length=1, null=True)
    DividedRoadFlag = models.CharField(db_column='divroad', max_length=1, null=True)
    ExtensionTypeFlag = models.CharField(db_column='exttyp', max_length=1, null=True)
    TrackTypeFlag = models.CharField(db_column='ttyp', max_length=1, null=True)
    DeckedRoadFlag = models.CharField(db_column='deckedroad', max_length=1, null=True)
    ArtificalPathFlag = models.CharField(db_column='artpath', max_length=1, null=True)
    HydrographicPersistenceFlag = models.CharField(db_column='persist', max_length=1, null=True)
    GeographicControlShortLinesFlag = models.CharField(db_column='gcseflg', max_length=1, null=True)
    LeftOffsetFlag = models.CharField(db_column='offsetl', max_length=1, null=True)
    RightOffsetFlag = models.CharField(db_column='offsetr', max_length=1, null=True)
    FromTigerNodeIdentifier = models.TextField(db_column='tnidf', null=True) # This field type is a guess.
    ToTigerNodeIdentifier = models.TextField(db_column='tnidt', null=True) # This field type is a guess.
    the_geom = models.MultiLineStringField(db_column='the_geom', srid=4326, null=True)
    objects = models.GeoManager()
    class Meta:
        db_table=u'censusedge2013'
        app_label='djangoproject'
    def __unicode__(self):
        return self.Name
    @staticmethod 
    def ImportShapeFiles(ShapeFileName):
        """Deletes existing Census Edge records and reimports census shape files"""
        CensusEdge.objects.all().delete()
        #print """shp2pgsql -s 4326 -a -g the_geom """ + ShapeFileName + """ censusedge2013 | psql -d coopgis"""
        os.system("""shp2pgsql -s 4326 -a -g the_geom """ + ShapeFileName + """ censusedge2013 | psql -d coopgis""")
    @staticmethod
    def PopulateRoadsTable():
        Road.objects.all().delete()
        CensusEdges=CensusEdge.objects.all().filter(RoadFlag='Y')
        MainRoadList=['120th Ave']
        Total=CensusEdge.objects.filter(RoadFlag='Y').count()
        Count = 0
        for i in CensusEdges:
            New=Road()
            New.Name=i.Name
            if(not New.Name):
                New.Name = ''
            if('I-' in New.Name):
                New.InterstateIndicator=True
                New.Number=CensusEdge.GetDigitsOnly(New.Name)
                New.SymbologyRoadTypeFlag='I'
            elif('US' in New.Name):
                New.USHighwayIndicator=True
                New.SymbologyRoadTypeFlag='U'
                New.Number=CensusEdge.GetDigitsOnly(New.Name)
            elif('State Hwy' in New.Name):
                New.StateHighwayIndicator=True
                New.SymbologyRoadTypeFlag='S'
            elif(New.Name in MainRoadList):
                New.MainRoadIndicator=True
                New.SymbologyRoadTypeFlag='M'
            else:
                New.SymbologyRoadTypeFlag='O'
            New.LeftFromAddress=i.LeftFromAddress
            New.RightFromAddress=i.RightFromAddress
            New.LeftToAddress=i.LeftToAddress
            New.RightToAddress=i.RightToAddress
            New.Line=i.the_geom[0]
            New.save()
            if(Count % 250 == 0):
                print "On:  " + str(Count) + "   of   " + str(Total)
            Count = Count + 1
    @staticmethod
    def GetDigitsOnly(String):
        NewStringList=[]
        for i in String:
            if(i in ['1', '2', '3', '4', '5', '6', '7', '8', '9']):
                NewStringList.append(i)
        return ''.join(NewStringList)


 
class ReportPageNumberPolygon(models.Model):
    """Polygons representing the page number of a portion of the system.  These are temporary constructs, 
       generated for each individual report so no need to transfer between the client and server or use commands."""
    Name=models.CharField(max_length=250, db_column='name')
    MapReportIdentifier=models.CharField(max_length=250, db_column='mapreportidentifier')
    Page=models.CharField(max_length=250, db_column='pagenumber')
    Polygon=models.PolygonField(db_column='the_geom', srid=4326)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisreportpagenumberpolygon'
        app_label='djangoproject'
    def Create(self, X1, Y1, X2, Y2, srid, Name, MapReportIdentifier, Page):
        Point1=Point(X1, Y1, srid=srid)
        Point2=Point(X1, Y2, srid=srid)
        Point3=Point(X2, Y2, srid=srid)
        Point4=Point(X2, Y1, srid=srid)
        ring=LinearRing(Point1.coords, Point2.coords, Point3.coords, Point4.coords, Point1.coords)
        New=ReportPageNumberPolygon()
        New.Polygon=Polygon(ring)
        New.Name=Name
        New.MapReportIdentifier=MapReportIdentifier
        New.Page=Page
        New.save()
        

def SnapLineToRoad(line, SnapDistance, LineSRID=djangoproject.settings.COOPGISGPSSRID):
    if(not line):
        return None
    Points=[]
    for i in line.coords:
        Points.append(Point(x=i[0], y=i[1], 
                      srid=LineSRID).transform(djangoproject.settings.COOPGISSRID, clone=True))
    if(len(Points) < 2):
        return line
    FirstPointRoads=Road.objects.filter(Line__distance_lte=(Points[0], SnapDistance))
    if(FirstPointRoads):
        Distance = SnapDistance + 1
        ClosestPoint = FindClosestPoint(FirstPointRoads, SnapDistance, Points[0])
        Points[0]=ClosestPoint
    SecondPointRoads=Road.objects.filter(Line__distance_lte=(Points[-1], SnapDistance))
    if(SecondPointRoads):
        Distance = SnapDistance + 1
        ClosestPoint = FindClosestPoint(SecondPointRoads, SnapDistance, Points[-1])
        Points[-1]=ClosestPoint
    NewLine=LineString(Points, srid=djangoproject.settings.COOPGISSRID)
    return NewLine

def FindClosestPoint(Roads, SnapDistance, point):
    Points=[]
    for road in Roads:
        for i in road.Line.coords:
            Points.append(Point(x=i[0], y=i[1], srid=road.Line.srid))
    Distance=SnapDistance + 1
    CurrentPoint=Points[0]
    for i in Points:
        if(point.distance(i) < Distance):
            Distance=point.distance(i)
            CurrentPoint=i
    return i

class GPSTrace(models.Model):
    """GPSTrace holds temporary Traces, used to make other objects (Road Lines, Polygons, etc)"""
    Point=models.PointField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    Order=models.IntegerField(unique=True)  #Order in which the trace is to be intrepreted
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgisgpstrace'
        app_label='djangoproject'
    def GetLine(self):
        GPSTraces=GPSTrace.objects.all().order_by('Order')
        Points=[]
        for i in GPSTraces:
            Points.append(i.Point)
        if(not Points):
            return None
        return LineString(Points, srid=djangoproject.settings.COOPGISSRID)


try:
    admin.site.register(BoardDistrict, admin.GeoModelAdmin)
except:
    pass

class LandmarkType(models.Model):
    """LandmarkType is an obstacle in the COOP system; e.g.: Septic Tank, Water Line"""
    Name=models.CharField(max_length=250, db_column='name')
    Description=models.TextField(db_column='description')
    PointIndicator=models.BooleanField(db_column='pointindicator')
    LineIndicator=models.BooleanField(db_column='lineindicator')
    PolygonIndicator=models.BooleanField(db_column='polygonindicator')
    ResidesOnServerIndicator=models.NullBooleanField(db_column='residesonserverindicator', null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgislandmarktype'
        app_label='djangoproject'
    def __unicode__(self):
        return self.Name
    def GetIndexWhenReverseSorted(self):
        Objects=LandmarkType.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()

class LandmarkPoint(models.Model):
    """LandmarkPoint is an obstacle best described by a point; e.g: radio tower"""
    Name=models.CharField(max_length=250, db_column='name')
    Description=models.TextField(db_column='description')
    Point=models.PointField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    LandmarkType=models.ForeignKey('LandmarkType', blank=True, null=True, on_delete=models.PROTECT)
    ResidesOnServerIndicator=models.NullBooleanField(db_column='residesonserverindicator', null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    SymbologyText=models.TextField(db_column='symbologytext', blank=True, null=True)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgislandmarkpoint'
        app_label='djangoproject'
    def GetIndexWhenReverseSorted(self):
        Objects=LandmarkType.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()

class LandmarkLine(models.Model):
    """LandmarkLine is an obstacle best described by a line; e.g.: water line"""
    Name=models.CharField(db_column='name', max_length=250)
    Description=models.TextField(db_column='description')
    Line=models.LineStringField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    LandmarkType=models.ForeignKey('LandmarkType', blank=True, null=True, on_delete=models.PROTECT)
    ResidesOnServerIndicator=models.NullBooleanField(db_column='residesonserverindicator', null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    SymbologyText=models.TextField(db_column='symbologytext', blank=True, null=True)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgislandmarkline'
        app_label='djangoproject'
    def GetIndexWhenReverseSorted(self):
        Objects=LandmarkType.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()

class LandmarkPolygon(models.Model):
    """LandmarkPolygon is an obstacle best described by a polygon; e.g.: swimming pool, septic tank"""
    Name=models.CharField(max_length=250, db_column='name')
    Description=models.TextField(db_column='description')
    Polygon=models.PolygonField(db_column='the_geom', srid=djangoproject.settings.COOPGISSRID)
    LandmarkType=models.ForeignKey('LandmarkType', blank=True, null=True, on_delete=models.PROTECT)
    ResidesOnServerIndicator=models.NullBooleanField(db_column='residesonserverindicator', null=True, blank=True)
    CreateCommand=models.ForeignKey('Command', null=True, blank=True, on_delete=models.SET_NULL)
    SymbologyText=models.TextField(db_column='symbologytext', blank=True, null=True)
    objects=models.GeoManager()
    class Meta:
        db_table=u'coopgislandmarkpolygon'
        app_label='djangoproject'
    def GetIndexWhenReverseSorted(self):
        Objects=LandmarkType.objects.all().order_by('-id')
        i = 0
        while(True):
            if(Objects[i] == self):
                return i
            i = i + 1
    def GetCommandidData(self):
        if(self.ResidesOnServerIndicator):
            return self.id, None
        return None, self.GetIndexWhenReverseSorted()

#used by LandmarkPoint, LandmarkLine and LandmarkPolygon
def GenerateLandmarkSymbologyTextValue(Landmark):
    delimiter=':'
    value = str(Landmark.id) + delimiter + Landmark.LandmarkType.Name + delimiter + Landmark.Name
    return value
    

class LandmarkTypeAdmin(admin.ModelAdmin):
    pass

try:
    admin.site.register(LandmarkType, GeoModelAdmin)
except:
    pass
